package com.hbnu.WebSocket;

import com.alibaba.fastjson.JSON;
import com.hbnu.pojo.Room;
import com.hbnu.pojo.RoomMember;
import com.hbnu.pojo.User;
import com.hbnu.service.LoginService;
import com.hbnu.service.RoomService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class RoomWebSocketHandler extends TextWebSocketHandler {

    private static final Logger log = LoggerFactory.getLogger(RoomWebSocketHandler.class);

    @Autowired
    private RoomService roomService;
    
    @Autowired
    private LoginService loginService;
    
    @Autowired
    private com.hbnu.service.impl.WordService wordService;

    // 房间ID生成器 - 不再使用，改为使用数据库生成的房间ID
    // private static final AtomicInteger roomIdGenerator = new AtomicInteger(100000);
    
    // 房间管理 - 使用线程安全的集合
    private final Map<Integer, RoomInfo> rooms = new ConcurrentHashMap<>();
    private final Map<Integer, Set<WebSocketSession>> roomSessions = new ConcurrentHashMap<>();
    private final Map<Integer, Set<String>> roomReadyUsers = new ConcurrentHashMap<>();
    
    // 会话管理 - 使用线程安全的集合
    private final Map<WebSocketSession, String> sessionUsers = new ConcurrentHashMap<>();
    private final Map<WebSocketSession, Integer> sessionRooms = new ConcurrentHashMap<>();
    
    // 房间信息内部类
    private static class RoomInfo {
        private Integer roomId;
        private String roomName;
        private String creatorId;
        private LocalDateTime createTime;
        private Set<String> members;
        private int maxMembers;
        
        public RoomInfo(Integer roomId, String roomName, String creatorId) {
            this.roomId = roomId;
            this.roomName = roomName;
            this.creatorId = creatorId;
            this.createTime = LocalDateTime.now();
            this.members = new HashSet<>();
            this.maxMembers = 6; // 默认最大6人
            this.members.add(creatorId);
        }
        
        // Getters and setters
        public Integer getRoomId() { return roomId; }
        public String getRoomName() { return roomName; }
        public String getCreatorId() { return creatorId; }
        public LocalDateTime getCreateTime() { return createTime; }
        public Set<String> getMembers() { return members; }
        public int getMaxMembers() { return maxMembers; }
        public int getCurrentMemberCount() { return members.size(); }
        public boolean isFull() { return members.size() >= maxMembers; }
        
        public boolean addMember(String userId) {
            if (isFull() || members.contains(userId)) {
                return false;
            }
            return members.add(userId);
        }
        
        public boolean removeMember(String userId) {
            return members.remove(userId);
        }
        
        public boolean isEmpty() {
            return members.isEmpty();
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        log.info("WebSocket连接建立: sessionId={}, remoteAddress={}, uri={}", 
                session.getId(), 
                session.getRemoteAddress(), 
                session.getUri());
        
        // 记录当前活跃连接数
        log.info("当前活跃连接数: {}", sessionUsers.size() + 1);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        try {
            String payload = message.getPayload();
            log.info("收到WebSocket消息: sessionId={}, payload={}", session.getId(), payload);
            
            if (payload == null || payload.trim().isEmpty()) {
                log.warn("收到空消息: sessionId={}", session.getId());
                sendErrorMessage(session, "消息内容不能为空");
                return;
            }
            
            Map<String, Object> msg = JSON.parseObject(payload, Map.class);
            String action = (String) msg.get("action");
            
            if (action == null || action.trim().isEmpty()) {
                log.warn("消息缺少action字段: sessionId={}, payload={}", session.getId(), payload);
                sendErrorMessage(session, "消息格式错误：缺少action字段");
                return;
            }
            
            log.info("处理动作: sessionId={}, action={}", session.getId(), action);
            
            switch (action) {
                case "create_room":
                    handleCreate(session, msg);
                    break;
                case "join_room":
                    handleJoin(session, msg);
                    break;
                case "toggle_ready":
                    handleReady(session, msg);
                    break;
                case "start_game":
                    handleStart(session, msg);
                    break;
                case "leave_room":
                    handleLeave(session, msg);
                    break;
                case "get_room_info":
                    handleGetRoomInfo(session, msg);
                    break;
                case "draw_stroke":
                    handleDrawStroke(session, msg);
                    break;
                case "clear_canvas":
                    handleClearCanvas(session, msg);
                    break;
                case "chat_message":
                    handleChatMessage(session, msg);
                    break;
                case "get_random_word":
                    handleGetRandomWord(session, msg);
                    break;
                default:
                    log.warn("未知的动作类型: {}", action);
                    sendErrorMessage(session, "未知的动作类型: " + action);
                    break;
            }
        } catch (Exception e) {
            log.error("处理WebSocket消息时发生错误", e);
            sendErrorMessage(session, "消息处理失败: " + e.getMessage());
        }
    }

    /**
     * 处理创建房间
     */
    private void handleCreate(WebSocketSession session, Map<String, Object> msg) throws IOException {
        try {
            String userId = (String) msg.get("userId");
            String roomName = (String) msg.get("roomName");
            
            log.info("创建房间请求: userId='{}', roomName='{}', userIdType={}, roomNameType={}", 
                userId, roomName, 
                userId != null ? userId.getClass().getSimpleName() : "null",
                roomName != null ? roomName.getClass().getSimpleName() : "null");
            
            if (userId == null || roomName == null) {
                sendErrorMessage(session, "用户ID和房间名不能为空");
                return;
            }
            
            // 检查userId是否为空字符串
            if (userId.trim().isEmpty()) {
                log.warn("用户ID为空字符串: sessionId={}", session.getId());
                sendErrorMessage(session, "用户ID不能为空");
                return;
            }
            
            // 检查用户是否已在其他房间
            Integer existingRoomId = sessionRooms.get(session);
            if (existingRoomId != null) {
                log.warn("用户已在房间中: userId={}, existingRoomId={}", userId, existingRoomId);
                sendErrorMessage(session, "您已在房间中，请先离开当前房间");
                return;
            }
            
            // 通过数据库服务创建房间，获取统一的房间ID
            Room dbRoom = roomService.createRoom(roomName, userId);
            Integer roomId = dbRoom.getRoomId();
            
            // 将房间创建者添加到数据库的room_members表中
            try {
                roomService.addMemberToRoom(roomId, userId);
                log.info("房间创建者已添加到数据库: roomId={}, userId={}", roomId, userId);
            } catch (Exception e) {
                log.error("添加房间创建者到数据库失败: roomId={}, userId={}", roomId, userId, e);
                // 如果添加失败，删除已创建的房间
                try {
                    roomService.deleteRoom(roomId);
                } catch (Exception deleteEx) {
                    log.error("删除房间失败: roomId={}", roomId, deleteEx);
                }
                sendErrorMessage(session, "创建房间失败：无法添加创建者到房间");
                return;
            }
            
            // 创建WebSocket房间信息
            RoomInfo roomInfo = new RoomInfo(roomId, roomName, userId);
            // 将创建者添加到WebSocket房间成员列表
            roomInfo.addMember(userId);
            rooms.put(roomId, roomInfo);
            
            log.info("WebSocket房间创建成功，创建者已添加: roomId={}, userId={}, 当前人数={}", 
                roomId, userId, roomInfo.getCurrentMemberCount());
            
            // 将用户加入WebSocket会话管理
            sessionUsers.put(session, userId);
            sessionRooms.put(session, roomId);
            
            Set<WebSocketSession> members = Collections.synchronizedSet(new HashSet<>());
            members.add(session);
            roomSessions.put(roomId, members);
            
            // 初始化房间准备状态
            roomReadyUsers.put(roomId, Collections.synchronizedSet(new HashSet<>()));
            
            log.info("房间创建成功: roomId={}, roomName={}, creator={}", roomId, roomName, userId);
            
            // 发送成功响应
            Map<String, Object> response = new HashMap<>();
            response.put("action", "room_created");
            response.put("roomId", roomId);
            response.put("roomName", roomName);
            response.put("userId", userId);
            response.put("memberCount", 1);
            response.put("maxMembers", roomInfo.getMaxMembers());
            
            session.sendMessage(new TextMessage(JSON.toJSONString(response)));
            
        } catch (Exception e) {
            log.error("创建房间失败", e);
            sendErrorMessage(session, "创建房间失败: " + e.getMessage());
        }
    }

    /**
     * 处理加入房间
     */
    private void handleJoin(WebSocketSession session, Map<String, Object> msg) throws IOException {
        try {
            Object roomIdObj = msg.get("roomId");
            String userId = (String) msg.get("userId");
            
            log.info("加入房间请求: roomIdObj='{}', userId='{}', roomIdType={}, userIdType={}", 
                roomIdObj, userId,
                roomIdObj != null ? roomIdObj.getClass().getSimpleName() : "null",
                userId != null ? userId.getClass().getSimpleName() : "null");
            
            if (roomIdObj == null || userId == null) {
                sendErrorMessage(session, "房间ID和用户ID不能为空");
                return;
            }
            
            // 检查userId是否为空字符串
            if (userId.trim().isEmpty()) {
                log.warn("用户ID为空字符串: sessionId={}", session.getId());
                sendErrorMessage(session, "用户ID不能为空");
                return;
            }
            
            Integer roomId = Integer.valueOf(roomIdObj.toString());
            log.info("解析后的房间ID: {}", roomId);
            
            // 检查用户是否已在其他房间
            Integer existingRoomId = sessionRooms.get(session);
            if (existingRoomId != null) {
                log.warn("用户已在其他房间: userId={}, existingRoomId={}, targetRoomId={}", userId, existingRoomId, roomId);
                sendErrorMessage(session, "您已在房间中，请先离开当前房间");
                return;
            }
            
            // 检查房间是否存在（先检查WebSocket房间，再检查数据库房间）
            RoomInfo roomInfo = rooms.get(roomId);
            log.info("查找WebSocket房间结果: roomId={}, roomInfo={}, 当前房间数量={}", roomId, roomInfo != null ? "存在" : "不存在", rooms.size());
            
            if (roomInfo == null) {
                // WebSocket房间不存在，检查数据库中是否存在该房间
                try {
                    Room dbRoom = roomService.getRoomById(roomId);
                    if (dbRoom != null && "waiting".equals(dbRoom.getStatus())) {
                        // 数据库中存在该房间且状态为等待中，创建对应的WebSocket房间
                        log.info("从数据库恢复房间: roomId={}, roomName={}, creator={}", 
                            dbRoom.getRoomId(), dbRoom.getRoomName(), dbRoom.getCreatorId());
                        
                        roomInfo = new RoomInfo(dbRoom.getRoomId(), dbRoom.getRoomName(), dbRoom.getCreatorId());
                        rooms.put(roomId, roomInfo);
                        
                        // 初始化房间会话和准备状态
                        roomSessions.put(roomId, Collections.synchronizedSet(new HashSet<>()));
                        roomReadyUsers.put(roomId, Collections.synchronizedSet(new HashSet<>()));
                        
                        log.info("WebSocket房间恢复成功: roomId={}", roomId);
                    } else {
                        log.warn("数据库中房间不存在或状态不正确: roomId={}, dbRoom={}", roomId, dbRoom);
                        sendErrorMessage(session, "房间不存在或已关闭");
                        return;
                    }
                } catch (Exception e) {
                    log.error("查询数据库房间失败: roomId={}", roomId, e);
                    sendErrorMessage(session, "房间查询失败");
                    return;
                }
            }
            
            // 检查房间是否已满
            if (roomInfo.isFull()) {
                sendErrorMessage(session, "房间已满");
                return;
            }
            
            // 检查用户是否已在房间中（从数据库查询）
            try {
                boolean isUserInRoom = roomService.isUserInRoom(roomId, userId);
                if (isUserInRoom) {
                    log.info("用户已在房间中，直接确认加入: userId='{}', roomId={}", userId, roomId);
                    
                    // 更新WebSocket会话映射
                    sessionUsers.put(session, userId);
                    sessionRooms.put(session, roomId);
                    
                    Set<WebSocketSession> members = roomSessions.get(roomId);
                    if (members == null) {
                        members = Collections.synchronizedSet(new HashSet<>());
                        roomSessions.put(roomId, members);
                    }
                    members.add(session);
                    
                    // 发送成功响应给当前用户
                    Map<String, Object> response = new HashMap<>();
                    response.put("action", "room_joined");
                    response.put("roomId", roomId);
                    response.put("roomName", roomInfo.getRoomName());
                    response.put("userId", userId);
                    response.put("memberCount", roomInfo.getCurrentMemberCount());
                    response.put("maxMembers", roomInfo.getMaxMembers());
                    
                    session.sendMessage(new TextMessage(JSON.toJSONString(response)));
                    log.info("发送房间加入确认消息（用户已在房间）: roomId={}, userId={}", roomId, userId);
                    return;
                }
            } catch (Exception e) {
                log.error("检查用户房间状态失败: userId='{}', roomId={}", userId, roomId, e);
                sendErrorMessage(session, "检查房间状态失败");
                return;
            }
            
            // 先将用户添加到数据库
            try {
                boolean dbJoined = roomService.addMemberToRoom(roomId, userId);
                if (!dbJoined) {
                    log.error("数据库添加成员失败: roomId={}, userId={}", roomId, userId);
                    sendErrorMessage(session, "加入房间失败");
                    return;
                }
                log.info("用户成功添加到数据库: roomId={}, userId={}", roomId, userId);
            } catch (Exception e) {
                log.error("数据库操作失败: roomId={}, userId={}", roomId, userId, e);
                sendErrorMessage(session, "加入房间失败: 数据库错误");
                return;
            }
            
            // 然后加入WebSocket房间
            boolean joined = roomInfo.addMember(userId);
            if (!joined) {
                log.error("WebSocket房间添加成员失败: roomId={}, userId={}", roomId, userId);
                sendErrorMessage(session, "加入房间失败");
                return;
            }
            
            // WebSocket会话管理
            sessionUsers.put(session, userId);
            sessionRooms.put(session, roomId);
            
            Set<WebSocketSession> members = roomSessions.get(roomId);
            if (members == null) {
                members = Collections.synchronizedSet(new HashSet<>());
                roomSessions.put(roomId, members);
            }
            members.add(session);
            
            log.info("用户加入房间: roomId={}, userId={}, 当前人数={}", roomId, userId, roomInfo.getCurrentMemberCount());
            
            // 发送成功响应给当前用户
            Map<String, Object> response = new HashMap<>();
            response.put("action", "room_joined");
            response.put("roomId", roomId);
            response.put("roomName", roomInfo.getRoomName());
            response.put("userId", userId);
            response.put("memberCount", roomInfo.getCurrentMemberCount());
            response.put("maxMembers", roomInfo.getMaxMembers());
            
            session.sendMessage(new TextMessage(JSON.toJSONString(response)));
            log.info("发送房间加入确认消息: roomId={}, userId={}", roomId, userId);
            
            // 广播用户加入消息给其他用户
            Map<String, Object> joinMsg = new HashMap<>();
            joinMsg.put("action", "user_joined");
            joinMsg.put("userId", userId);
            joinMsg.put("memberCount", roomInfo.getCurrentMemberCount());
            joinMsg.put("message", userId + " 加入了房间");
            
            broadcastToOthers(roomId, session, JSON.toJSONString(joinMsg));
            
            // 自动刷新房间状态信息给所有用户
            broadcastRoomStatusUpdate(roomId);
            
        } catch (Exception e) {
            log.error("加入房间失败", e);
            sendErrorMessage(session, "加入房间失败: " + e.getMessage());
        }
    }

    /**
     * 处理准备状态
     */
    private void handleReady(WebSocketSession session, Map<String, Object> msg) throws IOException {
        try {
            Object roomIdObj = msg.get("roomId");
            String userId = (String) msg.get("userId");
            
            log.info("准备状态请求: roomIdObj='{}', userId='{}', roomIdType={}, userIdType={}", 
                roomIdObj, userId,
                roomIdObj != null ? roomIdObj.getClass().getSimpleName() : "null",
                userId != null ? userId.getClass().getSimpleName() : "null");
            
            if (roomIdObj == null || userId == null) {
                sendErrorMessage(session, "房间ID和用户ID不能为空");
                return;
            }
            
            // 检查userId是否为空字符串
            if (userId.trim().isEmpty()) {
                log.warn("用户ID为空字符串: sessionId={}", session.getId());
                sendErrorMessage(session, "用户ID不能为空");
                return;
            }
            
            Integer roomId = Integer.valueOf(roomIdObj.toString());
            log.info("解析后的房间ID: {}", roomId);
            
            log.info("处理准备状态: sessionId={}, userId='{}', roomId={}", session.getId(), userId, roomId);
        
        // 检查房间是否存在（先检查WebSocket房间，再检查数据库房间）
        RoomInfo roomInfo = rooms.get(roomId);
        log.info("准备状态-查找WebSocket房间: roomId={}, roomInfo={}", roomId, roomInfo != null ? "存在" : "不存在");
        
        if (roomInfo == null) {
            // WebSocket房间不存在，检查数据库中是否存在该房间
            try {
                Room dbRoom = roomService.getRoomById(roomId);
                if (dbRoom != null && "waiting".equals(dbRoom.getStatus())) {
                    // 数据库中存在该房间且状态为等待中，创建对应的WebSocket房间
                    log.info("准备状态-从数据库恢复房间: roomId={}, roomName={}, creator={}", 
                        dbRoom.getRoomId(), dbRoom.getRoomName(), dbRoom.getCreatorId());
                    
                    roomInfo = new RoomInfo(dbRoom.getRoomId(), dbRoom.getRoomName(), dbRoom.getCreatorId());
                    rooms.put(roomId, roomInfo);
                    
                    // 初始化房间会话和准备状态
                    roomSessions.put(roomId, Collections.synchronizedSet(new HashSet<>()));
                    roomReadyUsers.put(roomId, Collections.synchronizedSet(new HashSet<>()));
                    
                    log.info("准备状态-WebSocket房间恢复成功: roomId={}", roomId);
                } else {
                    log.warn("准备状态-数据库中房间不存在或状态不正确: roomId={}, dbRoom={}", roomId, dbRoom);
                    sendErrorMessage(session, "房间不存在");
                    return;
                }
            } catch (Exception e) {
                log.error("准备状态-查询数据库房间失败: roomId={}", roomId, e);
                sendErrorMessage(session, "房间查询失败");
                return;
            }
        }
        
        // 检查用户是否在房间中（从数据库查询）
        try {
            boolean isUserInRoom = roomService.isUserInRoom(roomId, userId);
            if (!isUserInRoom) {
                log.warn("用户不在房间中: userId='{}', roomId={}", userId, roomId);
                sendErrorMessage(session, "您不在该房间中");
                return;
            }
        } catch (Exception e) {
            log.error("检查用户房间状态失败: userId='{}', roomId={}", userId, roomId, e);
            sendErrorMessage(session, "检查房间状态失败");
            return;
        }
        
        // 确保用户会话已添加到WebSocket管理中
        sessionUsers.put(session, userId);
        sessionRooms.put(session, roomId);
        
        // 将用户会话添加到房间会话列表中
        Set<WebSocketSession> roomSessionSet = roomSessions.get(roomId);
        if (roomSessionSet == null) {
            roomSessionSet = Collections.synchronizedSet(new HashSet<>());
            roomSessions.put(roomId, roomSessionSet);
        }
        roomSessionSet.add(session);
        
        // 将用户添加到WebSocket房间成员列表中
        roomInfo.addMember(userId);
        
        log.info("用户会话已添加到WebSocket管理: sessionId={}, userId={}, roomId={}", 
            session.getId(), userId, roomId);
        
        // 更新内存中的准备状态
        Set<String> readyUsers = roomReadyUsers.get(roomId);
        if (readyUsers == null) {
            readyUsers = Collections.synchronizedSet(new HashSet<>());
            roomReadyUsers.put(roomId, readyUsers);
        }
        
        boolean isReady = readyUsers.contains(userId);
        if (isReady) {
            // 取消准备
            readyUsers.remove(userId);
            log.info("用户取消准备: roomId={}, userId={}", roomId, userId);
        } else {
            // 设置准备
            readyUsers.add(userId);
            log.info("用户准备: roomId={}, userId={}", roomId, userId);
        }
        
        // 广播准备状态
        Map<String, Object> readyMsg = new HashMap<>();
        readyMsg.put("action", "user_ready");
        readyMsg.put("userId", userId);
        readyMsg.put("isReady", !isReady);
        readyMsg.put("readyCount", readyUsers.size());
        readyMsg.put("memberCount", roomInfo.getCurrentMemberCount());
        readyMsg.put("message", userId + (isReady ? " 取消准备" : " 已准备"));
        
        broadcastToRoom(roomId, JSON.toJSONString(readyMsg));
        
        // 自动刷新房间状态信息给所有用户
        broadcastRoomStatusUpdate(roomId);
        
        } catch (Exception e) {
            log.error("处理准备状态失败", e);
            sendErrorMessage(session, "处理准备状态失败: " + e.getMessage());
        }
    }

    /**
     * 处理开始游戏
     */
    private void handleStart(WebSocketSession session, Map<String, Object> msg) throws IOException {
        // 优先从消息中获取参数
        Object roomIdObj = msg.get("roomId");
        String userId = (String) msg.get("userId");
        
        Integer roomId = null;
        
        // 如果消息中有参数，使用消息中的参数
        if (roomIdObj != null && userId != null) {
            roomId = Integer.valueOf(roomIdObj.toString());
            log.info("开始游戏-从消息获取参数: roomId={}, userId={}", roomId, userId);
        } else {
            // 否则从会话中获取
            roomId = sessionRooms.get(session);
            userId = sessionUsers.get(session);
            log.info("开始游戏-从会话获取参数: roomId={}, userId={}", roomId, userId);
        }
        
        if (roomId == null || userId == null) {
            sendErrorMessage(session, "用户未在房间中");
            return;
        }
        
        // 验证用户是否在数据库中的房间里
        try {
            boolean isUserInRoom = roomService.isUserInRoom(roomId, userId);
            if (!isUserInRoom) {
                log.warn("开始游戏-用户不在房间中: userId='{}', roomId={}", userId, roomId);
                sendErrorMessage(session, "您不在该房间中");
                return;
            }
        } catch (Exception e) {
            log.error("开始游戏-检查用户房间状态失败: userId='{}', roomId={}", userId, roomId, e);
            sendErrorMessage(session, "检查房间状态失败");
            return;
        }
        
        // 确保用户会话已添加到WebSocket管理中
        sessionUsers.put(session, userId);
        sessionRooms.put(session, roomId);
        
        // 检查房间是否存在
        RoomInfo roomInfo = rooms.get(roomId);
        if (roomInfo == null) {
            sendErrorMessage(session, "房间不存在");
            return;
        }
        
        // 检查是否是房主
        if (!roomInfo.getCreatorId().equals(userId)) {
            sendErrorMessage(session, "只有房主可以开始游戏");
            return;
        }
        
        // 检查房间人数
//        if (roomInfo.getCurrentMemberCount() < 2) {
//            sendErrorMessage(session, "至少需要2人才能开始游戏");
//            return;
//        }
        
        // 检查是否所有玩家都已准备
        Set<String> readyUsers = roomReadyUsers.get(roomId);
        if (readyUsers == null) {
            readyUsers = Collections.synchronizedSet(new HashSet<>());
            roomReadyUsers.put(roomId, readyUsers);
        }
        
        // 房主不需要准备，其他玩家都需要准备
        Set<String> otherMembers = new HashSet<>(roomInfo.getMembers());
        otherMembers.remove(roomInfo.getCreatorId());
        
        if (!readyUsers.containsAll(otherMembers)) {
            sendErrorMessage(session, "无法开始游戏，请确保所有玩家都已准备");
            return;
        }
        
        log.info("游戏开始: roomId={}, 房主={}, 参与人数={}", roomId, userId, roomInfo.getCurrentMemberCount());
        
        // 广播游戏开始消息
        Map<String, Object> startMsg = new HashMap<>();
        startMsg.put("action", "game_started");
        startMsg.put("roomId", roomId);
        startMsg.put("message", "游戏开始！");
        startMsg.put("memberCount", roomInfo.getCurrentMemberCount());
        
        broadcastToRoom(roomId, JSON.toJSONString(startMsg));
    }

    /**
     * 处理离开房间
     */
    private void handleLeave(WebSocketSession session, Map<String, Object> msg) throws IOException {
        // 优先从消息中获取参数
        Object roomIdObj = msg.get("roomId");
        String userId = (String) msg.get("userId");
        
        Integer roomId = null;
        
        // 如果消息中有参数，使用消息中的参数
        if (roomIdObj != null && userId != null) {
            roomId = Integer.valueOf(roomIdObj.toString());
            log.info("离开房间-从消息获取参数: roomId={}, userId={}", roomId, userId);
        } else {
            // 否则从会话中获取
            userId = sessionUsers.get(session);
            roomId = sessionRooms.get(session);
            log.info("离开房间-从会话获取参数: roomId={}, userId={}", roomId, userId);
        }
        
        if (userId == null || roomId == null) {
            sendErrorMessage(session, "用户未在房间中");
            return;
        }
        
        // 验证用户是否在数据库中的房间里
        try {
            boolean isUserInRoom = roomService.isUserInRoom(roomId, userId);
            if (!isUserInRoom) {
                log.warn("离开房间-用户不在房间中: userId='{}', roomId={}", userId, roomId);
                sendErrorMessage(session, "您不在该房间中");
                return;
            }
        } catch (Exception e) {
            log.error("离开房间-检查用户房间状态失败: userId='{}', roomId={}", userId, roomId, e);
            sendErrorMessage(session, "检查房间状态失败");
            return;
        }
        
        // 先从数据库中移除用户
        try {
            boolean dbRemoved = roomService.leaveRoom(roomId, userId);
            if (dbRemoved) {
                log.info("用户已从数据库中移除: roomId={}, userId={}", roomId, userId);
            } else {
                log.warn("数据库中移除用户失败: roomId={}, userId={}", roomId, userId);
            }
        } catch (Exception e) {
            log.error("数据库操作失败: roomId={}, userId={}", roomId, userId, e);
            // 即使数据库操作失败，也继续进行WebSocket清理
        }
        
        // 检查房间是否存在
        RoomInfo roomInfo = rooms.get(roomId);
        if (roomInfo != null) {
            // 从WebSocket房间中移除用户
            roomInfo.removeMember(userId);
            log.info("用户离开WebSocket房间: roomId={}, userId={}, 剩余人数={}", roomId, userId, roomInfo.getCurrentMemberCount());
        }
        
        // 从WebSocket会话中移除
        removeUserFromRoom(session, roomId, userId);
        
        // 发送离开成功消息
        Map<String, Object> response = new HashMap<>();
        response.put("action", "room_left");
        response.put("message", "已离开房间");
        
        session.sendMessage(new TextMessage(JSON.toJSONString(response)));
    }

    /**
     * 处理获取房间信息
     */
    private void handleGetRoomInfo(WebSocketSession session, Map<String, Object> msg) throws IOException {
        // 从消息中获取roomId和userId
        Object roomIdObj = msg.get("roomId");
        Object userIdObj = msg.get("userId");
        
        log.info("获取房间信息请求: sessionId={}, 消息中的roomId={}, 消息中的userId={}", 
                session.getId(), roomIdObj, userIdObj);
        
        if (roomIdObj == null || userIdObj == null) {
            log.warn("获取房间信息-缺少必要参数: roomId={}, userId={}", roomIdObj, userIdObj);
            sendErrorMessage(session, "缺少必要参数");
            return;
        }
        
        Integer roomId;
        String userId;
        
        try {
            roomId = Integer.valueOf(roomIdObj.toString());
            userId = userIdObj.toString().trim();
        } catch (NumberFormatException e) {
            log.warn("获取房间信息-参数格式错误: roomId={}, userId={}", roomIdObj, userIdObj);
            sendErrorMessage(session, "参数格式错误");
            return;
        }
        
        if (userId.isEmpty()) {
            log.warn("获取房间信息-userId为空");
            sendErrorMessage(session, "用户ID不能为空");
            return;
        }
        
        log.info("获取房间信息: sessionId={}, userId='{}', roomId={}", session.getId(), userId, roomId);
        
        // 检查房间是否存在（先检查WebSocket房间，再检查数据库房间）
        RoomInfo roomInfo = rooms.get(roomId);
        log.info("获取房间信息-查找WebSocket房间: roomId={}, roomInfo={}", roomId, roomInfo != null ? "存在" : "不存在");
        
        if (roomInfo == null) {
            // WebSocket房间不存在，检查数据库中是否存在该房间
            try {
                Room dbRoom = roomService.getRoomById(roomId);
                if (dbRoom != null && "waiting".equals(dbRoom.getStatus())) {
                    // 数据库中存在该房间且状态为等待中，创建对应的WebSocket房间
                    log.info("获取房间信息-从数据库恢复房间: roomId={}, roomName={}, creator={}", 
                        dbRoom.getRoomId(), dbRoom.getRoomName(), dbRoom.getCreatorId());
                    
                    roomInfo = new RoomInfo(dbRoom.getRoomId(), dbRoom.getRoomName(), dbRoom.getCreatorId());
                    rooms.put(roomId, roomInfo);
                    
                    // 初始化房间会话和准备状态
                    roomSessions.put(roomId, Collections.synchronizedSet(new HashSet<>()));
                    roomReadyUsers.put(roomId, Collections.synchronizedSet(new HashSet<>()));
                    
                    log.info("获取房间信息-WebSocket房间恢复成功: roomId={}", roomId);
                } else {
                    log.warn("获取房间信息-数据库中房间不存在或状态不正确: roomId={}, dbRoom={}", roomId, dbRoom);
                    sendErrorMessage(session, "房间不存在");
                    return;
                }
            } catch (Exception e) {
                log.error("获取房间信息-查询数据库房间失败: roomId={}", roomId, e);
                sendErrorMessage(session, "房间查询失败");
                return;
            }
        }
        
        // 检查用户是否在房间中（从数据库查询）
        List<String> orderedMembers = new ArrayList<>();
        try {
            Room dbRoom = roomService.getRoomById(roomId);
            if (dbRoom == null) {
                log.warn("获取房间信息-数据库中房间不存在: roomId={}", roomId);
                sendErrorMessage(session, "房间不存在");
                return;
            }
            
            // 检查用户是否为房间成员（从数据库查询）
            boolean isUserInRoom = roomService.isUserInRoom(roomId, userId);
            if (!isUserInRoom) {
                log.warn("获取房间信息-用户不在房间中: userId='{}', roomId={}", userId, roomId);
                sendErrorMessage(session, "用户未在房间中");
                return;
            }
            
            // 获取按加入时间排序的成员列表
            orderedMembers = roomService.getOrderedRoomMembers(roomId);
        } catch (Exception e) {
            log.error("检查用户房间状态失败: userId='{}', roomId={}", userId, roomId, e);
            sendErrorMessage(session, "检查房间状态失败");
            return;
        }
        
        log.info("获取房间信息-验证通过: userId='{}', roomId={}", userId, roomId);
        
        Set<String> readyUsers = roomReadyUsers.get(roomId);
        if (readyUsers == null) {
            readyUsers = Collections.synchronizedSet(new HashSet<>());
            roomReadyUsers.put(roomId, readyUsers);
        }
        
        Map<String, Object> response = new HashMap<>();
        response.put("action", "room_info");
        response.put("roomId", roomId);
        response.put("roomName", roomInfo.getRoomName());
        response.put("creatorId", roomInfo.getCreatorId());
        response.put("memberCount", roomInfo.getCurrentMemberCount());
        response.put("maxMembers", roomInfo.getMaxMembers());
        response.put("readyCount", readyUsers.size());
        response.put("members", orderedMembers); // 使用按加入时间排序的成员列表
        response.put("readyUsers", new ArrayList<>(readyUsers));
        response.put("createTime", roomInfo.getCreateTime().toString());
        
        session.sendMessage(new TextMessage(JSON.toJSONString(response)));
    }

    /**
     * 发送错误消息
     */
    private void sendErrorMessage(WebSocketSession session, String errorMsg) {
        try {
            Map<String, Object> error = new HashMap<>();
            error.put("action", "error");
            error.put("message", errorMsg);
            
            session.sendMessage(new TextMessage(JSON.toJSONString(error)));
            log.debug("发送错误消息: {}", errorMsg);
        } catch (IOException e) {
            log.error("发送错误消息失败", e);
        }
    }

    /**
     * 向房间内所有用户广播消息
     */
    private void broadcastToRoom(Integer roomId, String message) throws IOException {
        Set<WebSocketSession> members = roomSessions.get(roomId);
        if (members != null) {
            for (WebSocketSession session : members) {
                if (session.isOpen()) {
                    session.sendMessage(new TextMessage(message));
                }
            }
        }
    }

    /**
     * 向房间内其他用户广播消息（排除发送者）
     */
    private void broadcastToOthers(Integer roomId, WebSocketSession sender, String message) throws IOException {
        Set<WebSocketSession> members = roomSessions.get(roomId);
        if (members != null) {
            for (WebSocketSession session : members) {
                if (session.isOpen() && !session.equals(sender)) {
                    session.sendMessage(new TextMessage(message));
                }
            }
        }
    }

    /**
     * 从房间中移除用户
     */
    private void removeUserFromRoom(WebSocketSession session, Integer roomId, String userId) {
        // 从房间会话中移除
        Set<WebSocketSession> members = roomSessions.get(roomId);
        if (members != null) {
            members.remove(session);
            
            // 检查房间信息
            RoomInfo roomInfo = rooms.get(roomId);
            
            // 如果房间为空，清理所有房间数据
            if (members.isEmpty() || (roomInfo != null && roomInfo.isEmpty())) {
                roomSessions.remove(roomId);
                roomReadyUsers.remove(roomId);
                rooms.remove(roomId);
                log.info("房间已清理: roomId={}", roomId);
            } else {
                // 广播用户离开消息
                try {
                    Map<String, Object> leaveMsg = new HashMap<>();
                    leaveMsg.put("action", "user_left");
                    leaveMsg.put("userId", userId);
                    leaveMsg.put("memberCount", roomInfo != null ? roomInfo.getCurrentMemberCount() : members.size());
                    leaveMsg.put("message", userId + " 离开了房间");
                    
                    broadcastToRoom(roomId, JSON.toJSONString(leaveMsg));
                    
                    // 自动刷新房间状态信息给剩余用户
                    broadcastRoomStatusUpdate(roomId);
                } catch (IOException e) {
                    log.error("广播用户离开消息失败", e);
                }
            }
        }
        
        // 从准备状态中移除
        Set<String> readyUsers = roomReadyUsers.get(roomId);
        if (readyUsers != null) {
            readyUsers.remove(userId);
        }
        
        // 清理会话映射
        sessionUsers.remove(session);
        sessionRooms.remove(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        log.info("WebSocket连接关闭: {}, 状态: {}", session.getId(), status);
        
        String userId = sessionUsers.get(session);
        Integer roomId = sessionRooms.get(session);
        
        if (userId != null && roomId != null) {
            try {
                // 从房间中移除用户
                RoomInfo roomInfo = rooms.get(roomId);
                if (roomInfo != null) {
                    roomInfo.removeMember(userId);
                    log.info("连接断开，用户离开房间: roomId={}, userId={}", roomId, userId);
                }
                
                // 从WebSocket会话中移除用户
                removeUserFromRoom(session, roomId, userId);
                
            } catch (Exception e) {
                log.error("处理连接关闭时发生错误", e);
            }
        }
    }

    /**
     * 广播房间状态更新信息给房间内所有用户
     */
    private void broadcastRoomStatusUpdate(Integer roomId) {
        try {
            RoomInfo roomInfo = rooms.get(roomId);
            if (roomInfo == null) {
                log.warn("广播房间状态更新-房间不存在: roomId={}", roomId);
                return;
            }
            
            Set<String> readyUsers = roomReadyUsers.get(roomId);
            if (readyUsers == null) {
                readyUsers = Collections.synchronizedSet(new HashSet<>());
                roomReadyUsers.put(roomId, readyUsers);
            }
            
            // 构建成员详细信息列表
            List<Map<String, Object>> memberDetails = new ArrayList<>();
            for (String openid : roomInfo.getMembers()) {
                Map<String, Object> memberInfo = new HashMap<>();
                memberInfo.put("openid", openid);
                
                // 从数据库获取用户信息
                try {
                    User user = loginService.getUserByOpenid(openid);
                    if (user != null) {
                        memberInfo.put("username", user.getUsername());
                        memberInfo.put("avatarUrl", user.getAvatarUrl());
                    } else {
                        memberInfo.put("username", "未知用户");
                        memberInfo.put("avatarUrl", "");
                    }
                } catch (Exception e) {
                    log.warn("获取用户信息失败: openid={}", openid, e);
                    memberInfo.put("username", "未知用户");
                    memberInfo.put("avatarUrl", "");
                }
                
                memberDetails.add(memberInfo);
            }
            
            // 构建房间状态更新消息
            Map<String, Object> statusUpdate = new HashMap<>();
            statusUpdate.put("action", "room_status_update");
            statusUpdate.put("roomId", roomId);
            statusUpdate.put("roomName", roomInfo.getRoomName());
            statusUpdate.put("creatorId", roomInfo.getCreatorId());
            statusUpdate.put("memberCount", roomInfo.getCurrentMemberCount());
            statusUpdate.put("maxMembers", roomInfo.getMaxMembers());
            statusUpdate.put("readyCount", readyUsers.size());
            statusUpdate.put("members", new ArrayList<>(roomInfo.getMembers())); // 保持原有的openid列表
            statusUpdate.put("memberDetails", memberDetails); // 新增详细信息列表
            statusUpdate.put("readyUsers", new ArrayList<>(readyUsers));
            statusUpdate.put("timestamp", System.currentTimeMillis());
            
            // 广播给房间内所有用户
            broadcastToRoom(roomId, JSON.toJSONString(statusUpdate));
            
            log.info("房间状态更新已广播: roomId={}, memberCount={}, readyCount={}", 
                    roomId, roomInfo.getCurrentMemberCount(), readyUsers.size());
            
        } catch (Exception e) {
            log.error("广播房间状态更新失败: roomId={}", roomId, e);
        }
    }

    /**
     * 处理绘画笔画数据
     */
    private void handleDrawStroke(WebSocketSession session, Map<String, Object> msg) throws IOException {
        try {
            Integer roomId = sessionRooms.get(session);
            if (roomId == null) {
                sendErrorMessage(session, "您不在任何房间中");
                return;
            }

            String userId = (String) msg.get("userId");
            if (userId == null || userId.trim().isEmpty()) {
                sendErrorMessage(session, "用户ID不能为空");
                return;
            }

            // 获取绘画数据
            Map<String, Object> strokeData = (Map<String, Object>) msg.get("strokeData");
            if (strokeData == null) {
                sendErrorMessage(session, "绘画数据不能为空");
                return;
            }

            // 构建广播消息
            Map<String, Object> broadcastMsg = new HashMap<>();
            broadcastMsg.put("action", "draw_stroke");
            broadcastMsg.put("userId", userId);
            broadcastMsg.put("strokeData", strokeData);
            broadcastMsg.put("timestamp", System.currentTimeMillis());

            // 广播给房间内除发送者外的所有用户
            broadcastToRoomExceptSender(roomId, session, JSON.toJSONString(broadcastMsg));
            
            log.info("绘画笔画已广播: roomId={}, userId={}", roomId, userId);
            
        } catch (Exception e) {
            log.error("处理绘画笔画失败", e);
            sendErrorMessage(session, "处理绘画数据失败: " + e.getMessage());
        }
    }

    /**
     * 处理清空画布
     */
    private void handleClearCanvas(WebSocketSession session, Map<String, Object> msg) throws IOException {
        try {
            Integer roomId = sessionRooms.get(session);
            if (roomId == null) {
                sendErrorMessage(session, "您不在任何房间中");
                return;
            }

            String userId = (String) msg.get("userId");
            if (userId == null || userId.trim().isEmpty()) {
                sendErrorMessage(session, "用户ID不能为空");
                return;
            }

            // 构建广播消息
            Map<String, Object> broadcastMsg = new HashMap<>();
            broadcastMsg.put("action", "clear_canvas");
            broadcastMsg.put("userId", userId);
            broadcastMsg.put("timestamp", System.currentTimeMillis());

            // 广播给房间内除发送者外的所有用户
            broadcastToRoomExceptSender(roomId, session, JSON.toJSONString(broadcastMsg));
            
            log.info("清空画布已广播: roomId={}, userId={}", roomId, userId);
            
        } catch (Exception e) {
            log.error("处理清空画布失败", e);
            sendErrorMessage(session, "处理清空画布失败: " + e.getMessage());
        }
    }

    /**
     * 处理聊天消息
     */
    private void handleChatMessage(WebSocketSession session, Map<String, Object> msg) throws IOException {
        String userId = (String) msg.get("userId");
        Object roomIdObj = msg.get("roomId");
        String message = (String) msg.get("message");
        
        if (userId == null || roomIdObj == null || message == null) {
            sendErrorMessage(session, "聊天消息参数不完整");
            return;
        }
        
        Integer roomId = Integer.valueOf(roomIdObj.toString());
        
        // 验证用户是否在房间中
        RoomInfo roomInfo = rooms.get(roomId);
        if (roomInfo == null || !roomInfo.getMembers().contains(userId)) {
            sendErrorMessage(session, "用户不在房间中");
            return;
        }
        
        log.info("处理聊天消息: roomId={}, userId={}, message={}", roomId, userId, message);
        
        // 构建聊天消息
        Map<String, Object> chatMsg = new HashMap<>();
        chatMsg.put("action", "chat_message");
        chatMsg.put("roomId", roomId);
        chatMsg.put("sender", userId);
        chatMsg.put("message", message);
        chatMsg.put("timestamp", System.currentTimeMillis());
        
        // 广播给房间内所有用户（包括发送者）
        broadcastToRoom(roomId, JSON.toJSONString(chatMsg));
    }

    /**
     * 广播消息给房间内除发送者外的所有用户
     */
    private void broadcastToRoomExceptSender(Integer roomId, WebSocketSession senderSession, String message) {
        try {
            Set<WebSocketSession> sessions = roomSessions.get(roomId);
            if (sessions != null) {
                for (WebSocketSession session : sessions) {
                    if (session != senderSession && session.isOpen()) {
                        try {
                            session.sendMessage(new TextMessage(message));
                        } catch (Exception e) {
                            log.error("发送消息失败: sessionId={}", session.getId(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("广播消息失败: roomId={}", roomId, e);
        }
    }

    /**
     * 处理获取随机词汇
     */
    private void handleGetRandomWord(WebSocketSession session, Map<String, Object> msg) throws IOException {
        try {
            com.hbnu.pojo.Word randomWord = wordService.getRandomWord();
            
            Map<String, Object> response = new HashMap<>();
            response.put("type", "random_word");
            
            if (randomWord != null) {
                response.put("success", true);
                response.put("word", randomWord.getWordText());
                response.put("category", randomWord.getCategory());
                response.put("difficulty", randomWord.getDifficulty());
            } else {
                response.put("success", false);
                response.put("message", "获取词汇失败");
            }
            
            session.sendMessage(new TextMessage(JSON.toJSONString(response)));
            log.info("发送随机词汇: sessionId={}, word={}", session.getId(), 
                    randomWord != null ? randomWord.getWordText() : "null");
        } catch (Exception e) {
            log.error("处理获取随机词汇时发生错误", e);
            sendErrorMessage(session, "获取词汇失败: " + e.getMessage());
        }
    }

     @Override
     public void handleTransportError(WebSocketSession session, Throwable exception) {
         log.error("WebSocket传输错误: {}", session.getId(), exception);
     }
}